FAT テーブル
クラスタを管理するテーブル
ステータスとポインタの格納位置が同じなのが混乱ポイント
実際のFATテーブルでは、クラスタのステータスとポインタ(次のクラスタへのリンク)は同じ場所に格納されます。これは混乱を招く可能性がある設計ですが、FAT ファイルシステムの特徴的な点です。
あと、実際にクラスタがどこを指してるか(物理的なクラスタ・セクタの位置)はクラスタ番号から計算するらしい
かなりお手上げ感あるけど Claude に出力してもらったので一番下に貼っておく まずは簡単な実装
ステータスとポインタを持つ
code:c
// FAT エントリの型定義
typedef uint16_t fat_entry_t;
// FAT テーブルの構造体
typedef struct {
} fat_table_t;
// FAT テーブルの初期化
void init_fat_table(fat_table_t *fat) {
for (int i = 0; i < FAT_SIZE; i++) {
fat->tablei = CLUSTER_UNUSED; }
}
// クラスタの値を設定(状態と次のクラスタへのリンクを兼ねる)
void set_cluster_value(fat_table_t *fat, int cluster, fat_entry_t value) {
if (cluster >= 0 && cluster < FAT_SIZE) {
}
}
// クラスタの値(状態または次のクラスタ番号)を取得
fat_entry_t get_cluster_value(fat_table_t *fat, int cluster) {
if (cluster >= 0 && cluster < FAT_SIZE) {
}
return CLUSTER_RESERVED; // 範囲外のクラスタ
}
// クラスタの状態を文字列で取得
const char* get_cluster_state_string(fat_entry_t value) {
if (value == CLUSTER_UNUSED) return "Unused";
if (value == CLUSTER_RESERVED) return "Reserved";
if (value == CLUSTER_BAD) return "Bad";
if (value == CLUSTER_END) return "End of chain";
return "In use (Next cluster)";
}
// FAT テーブルの内容を表示
void print_fat_table(fat_table_t *fat) {
printf("FAT Table:\n");
for (int i = 0; i < FAT_SIZE; i++) {
printf("%03d: 0x%04X (%s)\n", i, fat->tablei, get_cluster_state_string(fat->tablei)); if ((i + 1) % 16 == 0) printf("\n");
}
}
// クラスタチェーンを表示
void print_cluster_chain(fat_table_t *fat, int start_cluster) {
printf("Cluster chain starting at %d: ", start_cluster);
int current = start_cluster;
while (current != CLUSTER_END && current != CLUSTER_BAD && current != CLUSTER_UNUSED) {
printf("%d -> ", current);
}
printf("%s\n", get_cluster_state_string(fat->tablecurrent)); }
int main() {
fat_table_t fat;
init_fat_table(&fat);
// サンプルのクラスタチェーンを作成
set_cluster_value(&fat, 2, 3); // クラスタ2は3を指す
set_cluster_value(&fat, 3, 4); // クラスタ3は4を指す
set_cluster_value(&fat, 4, CLUSTER_END); // クラスタ4はファイルの終端
// 別のクラスタチェーンを作成
set_cluster_value(&fat, 5, 6);
set_cluster_value(&fat, 6, 7);
set_cluster_value(&fat, 7, CLUSTER_END);
// 破損クラスタを設定
set_cluster_value(&fat, 10, CLUSTER_BAD);
// FAT テーブルの内容を表示
print_fat_table(&fat);
// クラスタチェーンを表示
print_cluster_chain(&fat, 2);
print_cluster_chain(&fat, 5);
return 0;
}
難しいほうの実装(クラスタ番号から物理的な位置を計算するバージョン)
ちゃんと読めばわかると思う
code:c
#define CLUSTER_SIZE 4096 // 8 sectors per cluster #define DATA_START_SECTOR 100 // データ領域の開始セクタ typedef uint16_t fat_entry_t;
typedef struct {
} fat_table_t;
void init_fat_table(fat_table_t *fat) {
for (int i = 0; i < FAT_SIZE; i++) {
fat->tablei = CLUSTER_UNUSED; }
}
void set_cluster_value(fat_table_t *fat, int cluster, fat_entry_t value) {
if (cluster >= 0 && cluster < FAT_SIZE) {
}
}
fat_entry_t get_cluster_value(fat_table_t *fat, int cluster) {
if (cluster >= 0 && cluster < FAT_SIZE) {
}
return CLUSTER_RESERVED;
}
// クラスタ番号から物理セクタ番号を計算
uint32_t cluster_to_sector(int cluster_number) {
return DATA_START_SECTOR + (cluster_number - 2) * (CLUSTER_SIZE / SECTOR_SIZE);
}
// クラスタ番号から物理バイトオフセットを計算
uint64_t cluster_to_byte_offset(int cluster_number) {
return (uint64_t)cluster_to_sector(cluster_number) * SECTOR_SIZE;
}
const char* get_cluster_state_string(fat_entry_t value) {
if (value == CLUSTER_UNUSED) return "Unused";
if (value == CLUSTER_RESERVED) return "Reserved";
if (value == CLUSTER_BAD) return "Bad";
if (value == CLUSTER_END) return "End of chain";
return "In use (Next cluster)";
}
void print_fat_table(fat_table_t *fat) {
printf("FAT Table:\n");
for (int i = 0; i < FAT_SIZE; i++) {
printf("%03d: 0x%04X (%s)\n", i, fat->tablei, get_cluster_state_string(fat->tablei)); if (i >= 2 && fat->tablei != CLUSTER_UNUSED) { printf(" Physical location: Sector %u, Byte offset %lu\n",
cluster_to_sector(i), cluster_to_byte_offset(i));
}
if ((i + 1) % 8 == 0) printf("\n");
}
}
void print_cluster_chain(fat_table_t *fat, int start_cluster) {
printf("Cluster chain starting at %d:\n", start_cluster);
int current = start_cluster;
while (current != CLUSTER_END && current != CLUSTER_BAD && current != CLUSTER_UNUSED) {
printf("Cluster %d -> Physical Sector %u (Byte offset %lu)\n",
current, cluster_to_sector(current), cluster_to_byte_offset(current));
}
printf("End state: %s\n", get_cluster_state_string(fat->tablecurrent)); }
int main() {
fat_table_t fat;
init_fat_table(&fat);
// サンプルのクラスタチェーンを作成
set_cluster_value(&fat, 2, 3);
set_cluster_value(&fat, 3, 4);
set_cluster_value(&fat, 4, CLUSTER_END);
set_cluster_value(&fat, 5, 6);
set_cluster_value(&fat, 6, 7);
set_cluster_value(&fat, 7, CLUSTER_END);
set_cluster_value(&fat, 10, CLUSTER_BAD);
print_fat_table(&fat);
printf("\nCluster chains:\n");
print_cluster_chain(&fat, 2);
print_cluster_chain(&fat, 5);
return 0;
}